package com.itheima.sharding.alg;

import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;

import java.util.Collection;

/**
 * 定义精准查询数据库的算法类 接口中的泛型与数据库的片键类型一致
 *      select * from t_order where user_id = ?
 */
public class Comm4Db implements PreciseShardingAlgorithm<Long>, RangeShardingAlgorithm<Long> {
    /**
     * 实现分库的算法
     * @param collection 一切配置中可用的数据源集合：ds1,ds2    从这里获得[ds$->{1..2}.t_order_$->{1..2}]
     * @param preciseShardingValue 数据库对应分片键的值 ---> user_id
     * @return 返回一个具体的数据源名称
     */
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {

        //获取逻辑表名称
        String logicTableName = preciseShardingValue.getLogicTableName();

        //1.获取分片键名称-->即数据库中列的名称 user_id
        String columnName = preciseShardingValue.getColumnName();

        //2.获取分片键的值
        Long value = preciseShardingValue.getValue();

        //3.根据分片键的值，计算出对应的数据源名称
        //   3.1 先计算出分片键的值对应的模数
        Long mod = value % 2 + 1;
        //   3.2 根据模数，从数据源集合中获取对应的数据源名称
        String dataSourceName = collection.stream().filter(dsName -> dsName.endsWith(mod+"")).findFirst().get();

        return dataSourceName;
    }

    /**
     *
     * @param collection 配置文件中的数据源集合 ds1 ds2
     * @param rangeShardingValue 分片值 即 BETWEEN user_id BETWEEN 1 AND 10
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        //获取逻辑表名
        String logicTableName = rangeShardingValue.getLogicTableName();
        //1.获取分片键名
        String shardingColumn = rangeShardingValue.getColumnName();
        //2.获取分片键值范围
        Range<Long> valueRange = rangeShardingValue.getValueRange();
        //3.根据分片键值范围，进行范围匹配
        if (valueRange.hasLowerBound()){//存在下限
            Long l = valueRange.lowerEndpoint();
        }
        if (valueRange.hasUpperBound()){//存在上限
            Long u = valueRange.upperEndpoint();
        }
        return collection;
    }
}
